package com.hifar.test.oaApi.common;

import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 * <pre>
 *    将对象流化成XML，每个类型对应一个{@link JAXBContext}，{@link JAXBContext} 是线程安全的，但是
 * {@link Marshaller}是非线程安全的，因此需要每次创建一个。
 * </pre>
 *
 */
public class JaxbXmlMarshaller implements ApiMarshaller {

	private static Map<Class<?>, JAXBContext> jaxbContextHashMap = new ConcurrentHashMap<Class<?>, JAXBContext>();

	public void marshaller(Object object, OutputStream outputStream) {
		try {
			Marshaller m = buildMarshaller(object.getClass());
			m.marshal(object, outputStream);
		} catch (JAXBException e) {
			throw new RuntimeException(e);
		}
	}

	private Marshaller buildMarshaller(Class<?> objectType) throws JAXBException {
		if (!jaxbContextHashMap.containsKey(objectType)) {
			JAXBContext context = JAXBContext.newInstance(objectType);
			jaxbContextHashMap.put(objectType, context);
		}
		JAXBContext context = jaxbContextHashMap.get(objectType);
		Marshaller marshaller = context.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
		return marshaller;
	}

	private Unmarshaller buildUnMarshaller(Class<?> objectType) throws JAXBException {
		if (!jaxbContextHashMap.containsKey(objectType)) {
			JAXBContext context = JAXBContext.newInstance(objectType);
			jaxbContextHashMap.put(objectType, context);
		}
		JAXBContext context = jaxbContextHashMap.get(objectType);
		Unmarshaller marshaller = context.createUnmarshaller();
		return marshaller;
	}

	public <T> T unmarshaller(String str, Class<T> apiResponse) {
		try {
			Unmarshaller m = buildUnMarshaller(apiResponse);
			return (T) m.unmarshal(new ByteArrayInputStream(ApiUtils.convertBytes(str)));
		} catch (JAXBException e) {
			throw new RuntimeException(e);
		}
	}
}
